<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="认证" tabindex="-1"><a class="header-anchor" href="#认证"><span>认证</span></a></h2>
<ul>
<li><a href="#introduction">介绍</a>
<ul>
<li><a href="#starter-kits">入门套件</a></li>
<li><a href="#introduction-database-considerations">数据库考虑因素</a></li>
<li><a href="#ecosystem-overview">生态系统概述</a></li>
</ul>
</li>
<li><a href="#authentication-quickstart">认证快速入门</a>
<ul>
<li><a href="#install-a-starter-kit">安装入门套件</a></li>
<li><a href="#retrieving-the-authenticated-user">检索经过身份验证的用户</a></li>
<li><a href="#protecting-routes">保护路由</a></li>
<li><a href="#login-throttling">登录节流</a></li>
</ul>
</li>
<li><a href="#authenticating-users">手动认证用户</a>
<ul>
<li><a href="#remembering-users">记住用户</a></li>
<li><a href="#other-authentication-methods">其他认证方法</a></li>
</ul>
</li>
<li><a href="#http-basic-authentication">HTTP基本认证</a>
<ul>
<li><a href="#stateless-http-basic-authentication">无状态HTTP基本认证</a></li>
</ul>
</li>
<li><a href="#logging-out">登出</a>
<ul>
<li><a href="#invalidating-sessions-on-other-devices">使其他设备上的会话失效</a></li>
</ul>
</li>
<li><a href="#password-confirmation">密码确认</a>
<ul>
<li><a href="#password-confirmation-configuration">配置</a></li>
<li><a href="#password-confirmation-routing">路由</a></li>
<li><a href="#password-confirmation-protecting-routes">保护路由</a></li>
</ul>
</li>
<li><a href="#adding-custom-guards">添加自定义守卫</a>
<ul>
<li><a href="#closure-request-guards">闭包请求守卫</a></li>
</ul>
</li>
<li><a href="#adding-custom-user-providers">添加自定义用户提供者</a>
<ul>
<li><a href="#the-user-provider-contract">用户提供者合同</a></li>
<li><a href="#the-authenticatable-contract">可认证合同</a></li>
</ul>
</li>
<li><a href="#automatic-password-rehashing">自动密码重新散列</a></li>
<li><a href="https://learnku.com/docs/laravel/11.x/socialite" target="_blank" rel="noopener noreferrer">社交认证</a></li>
<li><a href="#events">事件</a></li>
</ul>
<h2 id="介绍" tabindex="-1"><a class="header-anchor" href="#介绍"><span>介绍</span></a></h2>
<p>许多网络应用程序为用户提供了一种通过应用程序进行身份验证和“登录”的方式。在网络应用程序中实现此功能可能是一个复杂且潜在风险的任务。因此，Laravel致力于为您提供所需的工具，以快速、安全和轻松地实现认证。</p>
<p>在核心层面，Laravel的认证设施由“守卫”和“提供者”组成。守卫定义了如何为每个请求对用户进行身份验证。例如，Laravel提供了一个<code v-pre>session</code>守卫，它使用会话存储和cookie来维护状态。</p>
<p>提供者定义了如何从持久性存储中检索用户。Laravel支持使用 <a href="https://learnku.com/docs/laravel/11.x/eloquentmd" target="_blank" rel="noopener noreferrer">Eloquent</a> 和数据库查询构建器来检索用户。但是，您可以根据需要自由定义其他提供者以适应您的应用程序。</p>
<p>在Laravel中，你可以通过<code v-pre>config/auth.php</code>文件来配置应用程序的认证设置。这个文件包含了许多经过详细记录的选项，可以调整Laravel的认证服务的行为。</p>
<blockquote>
<p><strong>注意：</strong><br>
守卫（guards）和提供者（providers）不应与「角色」和「权限」混淆。如果想了解如何通过权限授权用户操作，请参考<a href="https://learnku.com/docs/laravel/11.x/authorizationmd" target="_blank" rel="noopener noreferrer">授权文档</a>。</p>
</blockquote>
<h3 id="入门套件" tabindex="-1"><a class="header-anchor" href="#入门套件"><span>入门套件</span></a></h3>
<p>想要快速开始吗？在一个新的Laravel应用程序中安装一个<a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd" target="_blank" rel="noopener noreferrer">Laravel应用程序入门套件</a>。在迁移数据库之后，打开浏览器并访问<code v-pre>/register</code>或分配给你的应用程序的任何其他URL。入门套件将负责为您搭建整个认证系统！</p>
<p>**即使你最终选择不在最终的Laravel应用程序中使用入门套件，安装<a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd#laravel-breeze" target="_blank" rel="noopener noreferrer">Laravel Breeze</a>入门套件仍然是一个很好的机会，可以学习如何在实际的Laravel项目中实现所有Laravel的认证功能。**由于Laravel Breeze为你创建了认证控制器、路由和视图，你可以查看这些文件中的代码，了解如何实现Laravel的认证功能。</p>
<h3 id="数据库考虑因素" tabindex="-1"><a class="header-anchor" href="#数据库考虑因素"><span>数据库考虑因素</span></a></h3>
<p>默认情况下，Laravel在<code v-pre>app/Models</code>目录中包含一个<code v-pre>App\Models\User</code> <a href="https://learnku.com/docs/laravel/11.x/eloquentmd" target="_blank" rel="noopener noreferrer">Eloquent模型</a>。这个模型可以与默认的Eloquent认证驱动程序一起使用。如果您的应用程序没有使用Eloquent，你可以使用<code v-pre>database</code>认证提供者，它使用Laravel查询构建器。</p>
<p>在为<code v-pre>App\Models\User</code>模型构建数据库模式时，请确保密码列至少有60个字符的长度。当然，在新的Laravel应用程序中包含的<code v-pre>users</code>表迁移已经创建了一个超过这个长度的列。</p>
<p>除此之外，你还应该验证您的<code v-pre>users</code>（或等效）表包含一个可为空的、长度为 100 个字符的字符串 <code v-pre>remember_token</code> 列。这个列将用于存储选择了「记住我」选项的用户的令牌，当他们登录到您的应用程序时。同样，新的 Laravel 应用程序中包含的默认<code v-pre>users</code>表迁移已经包含了这个列。</p>
<h3 id="生态系统概述" tabindex="-1"><a class="header-anchor" href="#生态系统概述"><span>生态系统概述</span></a></h3>
<p>Laravel提供了几个与认证相关的包。在继续之前，让我们回顾一下 Laravel 中的通用认证生态系统，并讨论每个包的预期目的。</p>
<p>首先，考虑认证的工作原理。当用户使用 Web 浏览器时，他们将通过登录表单提供他们的用户名和密码。如果这些凭据正确，应用程序将在用户的<a href="https://learnku.com/docs/laravel/11.x/sessionmd" target="_blank" rel="noopener noreferrer">会话</a>中存储有关已认证用户的信息。向浏览器发出的 cookie 包含会话 ID，以便应用程序的后续请求可以将用户与正确的会话关联起来。收到会话 cookie 后，应用程序将根据会话ID检索会话数据，注意已将认证信息存储在会话中，并将用户视为「已认证」。</p>
<p>当远程服务需要进行身份验证以访问API时，通常不会使用 cookie 进行身份验证，因为没有Web 浏览器。相反，远程服务在每个请求中向 API 发送 API 令牌。应用程序可以根据有效 API令牌表验证传入的令牌，并将请求「认证」为与该 API 令牌关联的用户执行的请求。</p>
<p>Laravel 的内置浏览器认证服务包括通过 <code v-pre>Auth</code> 和 <code v-pre>Session</code> 门面访问的内置认证和会话服务。这些功能为从 Web 浏览器发起的请求提供基于 cookie 的身份验证。它们提供了允许你验证用户凭据并对用户进行身份验证的方法。此外，这些服务将自动将正确的身份验证数据存储在用户的会话中，并发出用户的会话 cookie。如何使用这些服务的讨论包含在本文档中。</p>
<p><strong>应用程序入门套件</strong></p>
<p>正如本文档中所讨论的，你可以手动与这些认证服务交互，构建应用程序自己的认证层。然而，为了帮助您更快地开始，我们发布了提供完整、现代化脚手架的<a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd" target="_blank" rel="noopener noreferrer">免费包</a>，涵盖整个认证层。这些包括<a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd#laravel-breeze" target="_blank" rel="noopener noreferrer">Laravel Breeze</a>、<a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd#laravel-jetstream" target="_blank" rel="noopener noreferrer">Laravel Jetstream</a>和<a href="https://learnku.com/docs/laravel/11.x/fortifymd" target="_blank" rel="noopener noreferrer">Laravel Fortify</a>。</p>
<ul>
<li>
<p><strong>Laravel Breeze</strong>是Laravel所有认证功能的简单、最小实现，包括登录、注册、密码重置、电子邮件验证和密码确认。Laravel Breeze 的视图层由简单的<a href="https://learnku.com/docs/laravel/11.x/blademd" target="_blank" rel="noopener noreferrer">Blade模板</a>组成，使用<a href="https://tailwindcss.com/" target="_blank" rel="noopener noreferrer">Tailwind CSS</a>进行样式设计。要开始使用，请查看Laravel的<a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd" target="_blank" rel="noopener noreferrer">应用程序入门套件</a>文档。</p>
</li>
<li>
<p><strong>Laravel Fortify</strong> 是 Laravel 的无头身份验证后端，实现了本文档中许多功能，包括基于cookie 的身份验证，以及其他功能，如双因素身份验证和电子邮件验证。Fortify为Laravel Jetstream提供身份验证后端，也可以与<a href="https://learnku.com/docs/laravel/11.x/sanctummd" target="_blank" rel="noopener noreferrer">Laravel Sanctum</a>结合独立使用，为需要与Laravel进行身份验证的SPA提供身份验证。</p>
</li>
</ul>
<p><a href="https://jetstream.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Jetstream</a>是一个强大的应用程序入门套件，它消费并暴露了Laravel Fortify的身份验证服务，具有由<a href="https://tailwindcss.com/" target="_blank" rel="noopener noreferrer">Tailwind CSS</a>、<a href="https://livewire.laravel.com/" target="_blank" rel="noopener noreferrer">Livewire</a>和/或<a href="https://inertiajs.com/" target="_blank" rel="noopener noreferrer">Inertia</a>提供支持的美观、现代化的用户界面。Laravel Jetstream包括可选的双因素身份验证、团队支持、浏览器会话管理、个人资料管理，并与<a href="https://learnku.com/docs/laravel/11.x/sanctummd" target="_blank" rel="noopener noreferrer">Laravel Sanctum</a>进行了内置集成，以提供API令牌身份验证。下面将讨论Laravel的API身份验证服务。</p>
<h4 id="laravel的api身份验证服务" tabindex="-1"><a class="header-anchor" href="#laravel的api身份验证服务"><span>Laravel的API身份验证服务</span></a></h4>
<p>Laravel提供了两个可选包，帮助您管理API令牌并对使用API令牌发出的请求进行身份验证：<a href="https://learnku.com/docs/laravel/11.x/passportmd" target="_blank" rel="noopener noreferrer">Passport</a>和<a href="https://learnku.com/docs/laravel/11.x/sanctummd" target="_blank" rel="noopener noreferrer">Sanctum</a>。请注意，这些库和Laravel内置的基于cookie的身份验证库并不是互斥的。这些库主要关注API令牌身份验证，而内置的身份验证服务主要关注基于cookie的浏览器身份验证。许多应用程序将同时使用Laravel内置的基于cookie的身份验证服务和Laravel的API身份验证包之一。</p>
<p><strong>Passport</strong></p>
<p>Passport是一个OAuth2身份验证提供者，提供各种OAuth2“授权类型”，允许您发出各种类型的令牌。总的来说，这是一个用于API身份验证的强大而复杂的包。然而，大多数应用程序不需要OAuth2规范提供的复杂功能，这可能会让用户和开发人员感到困惑。此外，开发人员过去常常困惑于如何使用Passport这样的OAuth2身份验证提供者对SPA应用程序或移动应用程序进行身份验证。</p>
<p><strong>Sanctum</strong></p>
<p>为了应对OAuth2的复杂性和开发人员的困惑，我们着手构建一个更简单、更流畅的身份验证包，可以处理来自Web浏览器的第一方Web请求以及通过令牌的API请求。这一目标在发布<a href="https://learnku.com/docs/laravel/11.x/sanctummd" target="_blank" rel="noopener noreferrer">Laravel Sanctum</a>时得以实现，应该被视为首选和推荐的身份验证包，适用于将提供第一方Web用户界面以及API，或由单页面应用程序（SPA）提供支持的应用程序，该SPA与后端Laravel应用程序分开存在，或提供移动客户端的应用程序。</p>
<p>Laravel Sanctum 是一个混合了 web 和 API 的身份验证包，它让我们管理应用程序的整个身份验证过程成为可能，因为当基于 Sanctum 的应用程序收到请求时，Sanctum 将首先确定请求是否包含引用已验证 session 的 session cookie。Sanctum 通过调用我们前面讨论过的 Laravel 的内置身份验证服务来实现这一点。如果请求没有通过 session cookie 进行身份验证，Sanctum 将检查请求中的 API 令牌。如果存在 API 令牌，则 Sanctum 将使用该令牌对请求进行身份验证。要了解有关此过程的更多信息，请参阅 <a href="https://learnku.com/docs/laravel/11.x/sanctum#how-it-works" target="_blank" rel="noopener noreferrer">Sanctum</a> 的 工作原理 文档。</p>
<p>Laravel Sanctum 是我们选择与 <a href="https://jetstream.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Jetstream</a> 应用程序入门套件一起使用的 API 包，因为我们认为它最适合大多数 web 应用程序的身份验证需求。</p>
<h4 id="汇总-选择你的解决方案" tabindex="-1"><a class="header-anchor" href="#汇总-选择你的解决方案"><span>汇总 &amp; 选择你的解决方案</span></a></h4>
<p>总之，如果你的应用程序将使用浏览器访问，并且你正在构建一个单页面的 Laravel 应用程序，那么你的应用程序可以使用 Laravel 的内置身份验证服务<br>
接下来，如果你的应用程序提供将由第三方使用的 API ，你可以在 <a href="https://learnku.com/docs/laravel/11.x/passport" target="_blank" rel="noopener noreferrer">Passport</a> 或 <a href="https://learnku.com/docs/laravel/11.x/sanctum" target="_blank" rel="noopener noreferrer">Sanctum</a> 之间进行选择，为你的应用程序提供 API 令牌身份验证。一般来说，尽可能选择 Sanctum，因为它是 API 认证、SPA 认证和移动认证的简单、完整的解决方案，包括对「scopes」或「abilities」的支持。<br>
如果你正在构建一个将由 Laravel 后端支持的单页面应用程序（SPA），那么应该使用 <a href="https://learnku.com/docs/laravel/11.x/sanctum" target="_blank" rel="noopener noreferrer">Laravel Sanctum</a>。在使用 Sanctum 时，你需要 <a href="#authenticating-users">手动实现自己的后端验证路由</a> 或使用 <a href="https://learnku.com/docs/laravel/11.x/fortify" target="_blank" rel="noopener noreferrer">Laravel Fortify</a> 作为无 header 身份验证后端服务，为注册、密码重置、电子邮件验证等功能提供路由和控制器。</p>
<p>当应用程序确定必须使用 OAuth2 规范提供的所有特性时，可以选择 Passport。</p>
<p>而且，如果你想快速入门，我们很高兴推荐 <a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd#laravel-breez" target="_blank" rel="noopener noreferrer">Laravel Breeze</a> 作为启动新 Laravel 应用程序的快速方法，该应用程序已经使用了我们首选的 Laravel 内置身份验证服务和 Laravel Sanctum 身份验证技术栈。</p>
<h2 id="身份验证快速入门" tabindex="-1"><a class="header-anchor" href="#身份验证快速入门"><span>身份验证快速入门</span></a></h2>
<blockquote>
<p><strong>警告</strong><br>
文档的这一部分讨论了通过 <a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd" target="_blank" rel="noopener noreferrer">Laravel 应用入门套件</a> 对用户进行身份验证，其中包括可帮助你快速入门的 UI 脚手架。如果你想直接与 Laravel 的身份验证系统集成，请查看 <a href="#authenticating-users">手动验证用户</a> 上的文档。</p>
</blockquote>
<h3 id="安装入门套件" tabindex="-1"><a class="header-anchor" href="#安装入门套件"><span>安装入门套件</span></a></h3>
<p>首先，你应该 <a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd" target="_blank" rel="noopener noreferrer">安装 Laravel 应用入门套件</a>。我们当前的入门套件 Laravel Breeze 和 Laravel Jetstream 提供了设计精美的起点，可将身份验证纳入你的全新 Laravel 应用程序。</p>
<p>Laravel Breeze 是 Laravel 所有身份验证功能的最小型简单的实现，包括登录、注册、密码重置、电子邮件验证和密码确认。 Laravel Breeze 的视图层由简单的 <a href="https://learnku.com/docs/laravel/11.x/blademd" target="_blank" rel="noopener noreferrer">Blade templates</a> 和 <a href="https://tailwindcss.com/" target="_blank" rel="noopener noreferrer">Tailwind CSS</a> 组成。Breeze 还使用 Vue 或 React 提供了基于 <a href="https://inertiajs.com/" target="_blank" rel="noopener noreferrer">Inertia</a> 的脚手架选项。</p>
<p><a href="https://jetstream.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Jetstream</a> 是一个更强大的应用入门套件，它支持使用 <a href="https://laravel-livewire.com/" target="_blank" rel="noopener noreferrer">Livewire</a> 或 <a href="https://inertiajs.com/" target="_blank" rel="noopener noreferrer">Inertia and Vue</a> 来构建你的应用程序。 此外，Jetstream 还提供可选的双因素身份验证支持、团队、资料管理、浏览器 session 管理、通过 <a href="https://learnku.com/docs/laravel/11.x/sanctummd" target="_blank" rel="noopener noreferrer">Laravel Sanctum</a> 的 API 支持、帐户删除等。</p>
<h3 id="获取已认证的用户信息" tabindex="-1"><a class="header-anchor" href="#获取已认证的用户信息"><span>获取已认证的用户信息</span></a></h3>
<p>在安装身份验证入门套件并允许用户注册应用程序并对其进行身份验证之后，你通常需要与当前通过身份验证的用户进行交互。在处理传入请求时，你可以通过 <code v-pre>Auth</code> facade 的 <code v-pre>user</code> 方法访问通过身份验证的用户：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 获取当前的认证用户信息...</span></span>
<span class="line"><span class="token variable">$user</span> <span class="token operator">=</span> <span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">user</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 获取当前的认证用户ID...</span></span>
<span class="line"><span class="token variable">$id</span> <span class="token operator">=</span> <span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">id</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>或者，一旦用户通过身份验证，你就可以通过 <code v-pre>Illuminate\Http\Request</code> 实例访问通过身份验证的用户。请记住，使用类型提示的类将自动注入到控制器方法中。通过对 <code v-pre>Illuminate\Http\Request</code> 对象进行类型提示，你可以通过 Request 的 <code v-pre>user</code> 方法从应用程序中的任何控制器方法方便地访问通过身份验证的用户：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>RedirectResponse</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">FlightController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 更新现有航班的航班信息。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">update</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">RedirectResponse</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$user</span> <span class="token operator">=</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">user</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/flights'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="确定当前用户是否已通过身份验证" tabindex="-1"><a class="header-anchor" href="#确定当前用户是否已通过身份验证"><span>确定当前用户是否已通过身份验证</span></a></h4>
<p>要确定发出传入 HTTP 请求的用户是否通过身份验证，你可以在 <code v-pre>Auth</code> facade 上使用 <code v-pre>check</code> 方法。如果用户通过身份验证，此方法将返回 <code v-pre>true</code> ：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">check</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 该用户已登录...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
尽管可以使用 <code v-pre>check</code> 方法确定用户是否已通过身份验证，但在允许用户访问某些路由 / 控制器之前，你通常会使用中间件验证用户是否已通过身份验证。要了解更多信息，请查看有关 <a href="https://learnku.com/docs/laravel/11.x/authentication#protecting-routes" target="_blank" rel="noopener noreferrer">路由保护</a> 的文档。</p>
</blockquote>
<h3 id="保护路由" tabindex="-1"><a class="header-anchor" href="#保护路由"><span>保护路由</span></a></h3>
<p><a href="https://learnku.com/docs/laravel/11.x/middleware" target="_blank" rel="noopener noreferrer">路由中间件</a> 可用于仅允许通过身份验证的用户访问给定路由。 Laravel 附带了一个 <code v-pre>auth</code> 中间件， 它是 <code v-pre>Illuminate\Auth\Middleware\Authenticate</code> 类的 <a href="https://learnku.com/docs/laravel/11.x/middleware#middleware-alias" target="_blank" rel="noopener noreferrer">中间件别名</a> 。 这个中间件已经在 Laravel 内部别名化，所以您需要做的只是将中间件附加到路由定义上：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/flights'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 只有经过身份验证的用户才能访问此路由...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'auth'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="给未认证的用户设置重定向" tabindex="-1"><a class="header-anchor" href="#给未认证的用户设置重定向"><span>给未认证的用户设置重定向</span></a></h4>
<p>当 <code v-pre>auth</code> 中间件检测到未经身份验证的用户时，它将用户重定向到 <code v-pre>login</code> <a href="https://learnku.com/docs/laravel/11.x/routing#named-routes" target="_blank" rel="noopener noreferrer">命名路由</a>。 你可以通过更新应用程序的 <code v-pre>bootstrap/app.php</code> 文件中的 <code v-pre>redirectGuestsTo</code> 方法来修改此行为：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token operator">-></span><span class="token function">withMiddleware</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Middleware</span> <span class="token variable">$middleware</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$middleware</span><span class="token operator">-></span><span class="token function">redirectGuestsTo</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/login'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token comment">// 使用闭包...</span></span>
<span class="line">    <span class="token variable">$middleware</span><span class="token operator">-></span><span class="token function">redirectGuestsTo</span><span class="token punctuation">(</span><span class="token keyword">fn</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">route</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'login'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="指定看守器" tabindex="-1"><a class="header-anchor" href="#指定看守器"><span>指定看守器</span></a></h4>
<p>将 <code v-pre>auth</code> 中间件附加到路由时，你还可以指定应该使用哪个「guard」来验证用户。指定的 guard 应与 <code v-pre>auth.php</code> 配置文件的 <code v-pre>guards</code> 数组中的一个键相对应：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/flights'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 只有经过身份验证的用户才能访问此路由...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'auth:admin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="登录限流" tabindex="-1"><a class="header-anchor" href="#登录限流"><span>登录限流</span></a></h3>
<p>如果你使用的是 Laravel Breeze 或 Laravel Jetstream <a href="https://learnku.com/docs/laravel/11.x/starter-kits" target="_blank" rel="noopener noreferrer">入门套件</a>，那么在尝试登录的时候将自动应用速率限制。默认情况下，如果用户在多次尝试后未能提供正确的凭据，他们将在一分钟内无法登录。该限制对与用户的用户名 / 电子邮件地址及其 IP 地址是唯一的。</p>
<blockquote>
<p><strong>注意</strong><br>
如果你想对应用程序中的其他路由进行速率限制，请查看 <a href="https://learnku.com/docs/laravel/11.x/routing#rate-limiting" target="_blank" rel="noopener noreferrer">速率限制</a> 文档。</p>
</blockquote>
<h2 id="手动验证用户" tabindex="-1"><a class="header-anchor" href="#手动验证用户"><span>手动验证用户</span></a></h2>
<p>你并非一定要使用 Laravel 的 <a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd" target="_blank" rel="noopener noreferrer">应用入门套件</a> 附带的身份验证脚手架。如果你选择不使用这个脚手架，则需要直接使用 Laravel 身份验证类来管理用户身份验证。别担心，这也很容易！</p>
<p>我们将通过 <code v-pre>Auth</code> <a href="https://learnku.com/docs/laravel/11.x/facadesmd" target="_blank" rel="noopener noreferrer">facade</a>来访问 Laravel 的身份认证服务，因此我们需要确保在类的顶部导入 <code v-pre>Auth</code> facade。接下来，让我们看下 <code v-pre>attempt</code> 方法。<code v-pre>attempt</code> 方法通常用于处理应用程序「登录」表单的身份认证尝试。如果认证成功，你应当重新生成用户的<a href="https://learnku.com/docs/laravel/11.x/sessionmd" target="_blank" rel="noopener noreferrer">session</a> 以防止 <a href="https://en.wikipedia.org/wiki/Session_fixation" target="_blank" rel="noopener noreferrer">session 固化</a>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>RedirectResponse</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">LoginController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 处理身份认证尝试。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">authenticate</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">RedirectResponse</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$credentials</span> <span class="token operator">=</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">validate</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'email'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'required'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'email'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'password'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'required'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">attempt</span><span class="token punctuation">(</span><span class="token variable">$credentials</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">regenerate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">            <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">intended</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'dashboard'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">back</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">withErrors</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'email'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'The provided credentials do not match our records.'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">onlyInput</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'email'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>attempt</code> 方法的第一个参数接受一个键/值对数组。数组中的值将用于在你的数据库表中查找用户。所以，在上面的示例中，将通过 <code v-pre>email</code> 列的值检索用户。如果找到用户，数据库中存储的散列密码将与通过数组传递给方法的 <code v-pre>password</code> 值进行比较。你不应该对传入请求的 <code v-pre>password</code> 值进行 hash 处理，因为框架会在将值与数据库中的 hash 密码进行比较之前自动对其进行 hash 处理。如果两个 hash 密码匹配，则将为该用户启动经过认证的会话。</p>
<p>请记住，Laravel 的身份认证服务将基于你的身份认证守卫的「provider」配置从数据库检索用户。在默认的 <code v-pre>config/auth.php</code> 配置文件中，指定了 Eloquent 用户提供者，并指示其在检索用户时使用 <code v-pre>App\Models\User</code> 模型。根据应用程序的需求，你可以在配置文件中更改这些值。</p>
<p>如果身份验证成功，<code v-pre>attempt</code> 方法将返回 <code v-pre>true</code> 。否则，将返回 <code v-pre>false</code>。</p>
<p>Laravel 的重定向器提供的 <code v-pre>intended</code> 方法会将用户重定向到他们在被身份验证中间件拦截之前尝试访问的 URL。可以给此方法提供一个回退 URI，以防预期的目的地不可用。</p>
<h4 id="指定附加条件" tabindex="-1"><a class="header-anchor" href="#指定附加条件"><span>指定附加条件</span></a></h4>
<p>如果你愿意，除了用户的电子邮件和密码外，还可以向身份认证查询中添加额外的查询条件。为此，我们可以简单地将查询条件添加到传递给 <code v-pre>attempt</code> 方法的数组中。例如，我们可以验证用户是否被标记为「active」：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">attempt</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'email'</span> <span class="token operator">=></span> <span class="token variable">$email</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'password'</span> <span class="token operator">=></span> <span class="token variable">$password</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'active'</span> <span class="token operator">=></span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 认证成功...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>对于复杂的查询条件，你可以在凭证数组中提供闭包。此闭包将与查询实例一起调用，允许你根据应用程序的需要自定义查询：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">attempt</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'email'</span> <span class="token operator">=></span> <span class="token variable">$email</span><span class="token punctuation">,</span> </span>
<span class="line">    <span class="token string single-quoted-string">'password'</span> <span class="token operator">=></span> <span class="token variable">$password</span><span class="token punctuation">,</span> </span>
<span class="line">    <span class="token keyword">fn</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Builder</span> <span class="token variable">$query</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token variable">$query</span><span class="token operator">-></span><span class="token function">has</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'activeSubscription'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 认证成功...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>警告</strong><br>
在这些例子中，<code v-pre>email</code> 不是必需的选项，它只是作为一个例子。你应该使用与数据库表中的「用户名」对应的任何列名。</p>
</blockquote>
<p><code v-pre>attemptWhen</code> 方法接收一个闭包作为其第二个参数，可用于在实际验证用户之前对潜在用户执行更广泛的检查。闭包接收潜在用户并应返回 <code v-pre>true</code> 或 <code v-pre>false</code> 以指示用户是否可以通过身份验证：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">attemptWhen</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'email'</span> <span class="token operator">=></span> <span class="token variable">$email</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'password'</span> <span class="token operator">=></span> <span class="token variable">$password</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isNotBanned</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 认证成功...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="访问特定的守卫实例" tabindex="-1"><a class="header-anchor" href="#访问特定的守卫实例"><span>访问特定的守卫实例</span></a></h4>
<p>通过 <code v-pre>Auth</code> facade 的 <code v-pre>guard</code> 方法，你可以指定在对用户进行身份验证时要使用哪个 guard 实例。这允许你使用完全不同的可验证模型或用户表来管理应用程序的不同部分的验证。</p>
<p>传递给 <code v-pre>guard</code> 方法的守卫名称应对应于 <code v-pre>auth.php</code> 配置文件中配置的守卫：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">guard</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'admin'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">attempt</span><span class="token punctuation">(</span><span class="token variable">$credentials</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="记住用户" tabindex="-1"><a class="header-anchor" href="#记住用户"><span>记住用户</span></a></h3>
<p>许多 web 应用程序在其登录表单上提供了「记住我」复选框。如果你希望在应用程序中提供「记住我」功能，你可以将布尔值作为第二个参数传递给 <code v-pre>attempt</code> 方法。</p>
<p>当此值为 <code v-pre>true</code> 时，Laravel 会使用户无限期地保持认证状态，或直到他们手动登出。你的 <code v-pre>users</code> 表必须包括字符串 <code v-pre>remember_token</code> 列，它将用于存储「记住我」标记。新 Laravel 应用程序附带的 <code v-pre>users</code> 表迁移文件已经包括了这个列：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">attempt</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'email'</span> <span class="token operator">=></span> <span class="token variable">$email</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'password'</span> <span class="token operator">=></span> <span class="token variable">$password</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token variable">$remember</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 用户将被记住...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你的应用程序提供「记住我」的功能，你可以使用 <code v-pre>viaRemember</code> 方法来确定当前通过身份验证的用户是否使用「记住我」cookie 进行了身份验证：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">viaRemember</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="其他身份验证方法" tabindex="-1"><a class="header-anchor" href="#其他身份验证方法"><span>其他身份验证方法</span></a></h3>
<h4 id="验证用户实例" tabindex="-1"><a class="header-anchor" href="#验证用户实例"><span>验证用户实例</span></a></h4>
<p>如果你需要将已有的用户实例设置为当前认证的用户，你可以将用户实例传递给 <code v-pre>Auth</code> facade 的 <code v-pre>login</code> 方法。给定的用户实例必须是 <code v-pre>Illuminate\Contracts\Auth\Authenticatable</code> <a href="https://learnku.com/docs/laravel/11.x/contractsmd" target="_blank" rel="noopener noreferrer">契约</a>的一个实现。Laravel 中附带的 <code v-pre>App\Models\User</code> 模型已经实现了这个接口。当你已经有一个有效的用户实例时（例如用户直接向你的应用程序注册之后），此身份验证方法非常有用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">login</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在调用 <code v-pre>login</code> 方法时，你可以将布尔值作为第二个参数传递。此值指示是否需要认证会话的「记住我」功能。记住，这意味着会话将无限期地进行认证，或直到用户手动退出应用程序：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">login</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token variable">$remember</span> <span class="token operator">=</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果需要，你可以在调用 <code v-pre>login</code> 方法之前指定身份验证守卫：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">guard</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'admin'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">login</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="通过-id-对用户进行身份验证" tabindex="-1"><a class="header-anchor" href="#通过-id-对用户进行身份验证"><span>通过 ID 对用户进行身份验证</span></a></h4>
<p>要使用数据库记录的主键对用户进行身份验证，你可以使用 <code v-pre>loginUsingId</code> 方法。此方法接受你要验证的用户的主键：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">loginUsingId</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你可以将布尔值作为第二个参数传递给 <code v-pre>loginUsingId</code> 方法。此值指示通过身份验证的 session 是否需要「记住我」功能。请记住，这意味着 session 将无限期地进行身份验证，或者直到用户手动注销应用程序为止：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">loginUsingId</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token variable">$remember</span> <span class="token operator">=</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="只验证一次" tabindex="-1"><a class="header-anchor" href="#只验证一次"><span>只验证一次</span></a></h4>
<p>你可以使用 <code v-pre>once</code> 方法通过应用程序对单个请求的用户进行身份验证。调用此方法时不会使用 session 或 cookie：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">once</span><span class="token punctuation">(</span><span class="token variable">$credentials</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="http-basic-用户认证" tabindex="-1"><a class="header-anchor" href="#http-basic-用户认证"><span>HTTP Basic 用户认证</span></a></h2>
<p><a href="https://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank" rel="noopener noreferrer">HTTP Basic 用户认证</a> 提供了一种快速的方式来认证你的应用用户，而不需要设置专门的「登录」页面。要开始，只需要将 <code v-pre>auth.basic</code> <a href="https://learnku.com/docs/laravel/11.x/middlewaremd" target="_blank" rel="noopener noreferrer">中间件</a>附加到一个路由上。<code v-pre>auth.basic</code> 中间件已包含在 Laravel 框架内，因此你不需要定义它：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/profile'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 只有认证用户才能访问此路由...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'auth.basic'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>一旦中间件被附加到路由上，当你在浏览器中访问该路由时，系统会自动提示你输入凭证。默认情况下，<code v-pre>auth.basic</code> 中间件会假设你的 <code v-pre>users</code> 数据库表中的 <code v-pre>email</code> 列是用户的「用户名」。</p>
<h4 id="关于-fastcgi-的说明" tabindex="-1"><a class="header-anchor" href="#关于-fastcgi-的说明"><span>关于 FastCGI 的说明</span></a></h4>
<p>如果你使用 PHP FastCGI 和 Apache 来服务你的 Laravel 应用程序，HTTP Basic 认证可能无法正常工作。为了纠正这些问题，可以在应用程序的 <code v-pre>.htaccess</code> 文件中添加以下行：</p>
<div class="language-apache line-numbers-mode" data-highlighter="prismjs" data-ext="apache" data-title="apache"><pre v-pre class="language-apache"><code><span class="line">RewriteCond %{HTTP:Authorization} ^(.+)$</span>
<span class="line">RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="无状态-http-basic-认证" tabindex="-1"><a class="header-anchor" href="#无状态-http-basic-认证"><span>无状态 HTTP Basic 认证</span></a></h3>
<p>你也可以使用 HTTP Basic 认证，而不在会话中设置用户标识符 cookie。如果你选择使用 HTTP 认证来认证应用程序的 API 请求，这主要是有帮助的。要做到这一点，<a href="https://learnku.com/docs/laravel/11.x/middlewaremd" target="_blank" rel="noopener noreferrer">定义一个中间件</a>并调用 <code v-pre>onceBasic</code> 方法。如果 <code v-pre>onceBasic</code> 方法没有返回响应，请求可以进一步传递到应用程序中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Closure</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Symfony<span class="token punctuation">\</span>Component<span class="token punctuation">\</span>HttpFoundation<span class="token punctuation">\</span>Response</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">AuthenticateOnceWithBasicAuth</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 处理传入的请求。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name"><span class="token punctuation">\</span>Closure</span>(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">handle</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">Closure</span> <span class="token variable">$next</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">Response</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">onceBasic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">?</span><span class="token punctuation">:</span> <span class="token variable">$next</span><span class="token punctuation">(</span><span class="token variable">$request</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接下来，将中间件附加到路由：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/api/user'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 只有认证用户才能访问此路由...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token class-name static-context">AuthenticateOnceWithBasicAuth</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="登出" tabindex="-1"><a class="header-anchor" href="#登出"><span>登出</span></a></h2>
<p>为了手动将用户从你的应用程序中登出，你可以使用 <code v-pre>Auth</code> facade 提供的 <code v-pre>logout</code> 方法。这将从用户的会话中移除认证信息，这样后续请求就不会被认证。</p>
<p>除了调用 <code v-pre>logout</code> 方法外，建议你将用户的 session 置为过期，并重新生成其 <a href="https://learnku.com/docs/laravel/11.x/csrfmd" target="_blank" rel="noopener noreferrer">CSRF 令牌</a>。注销用户后，通常会将用户重定向到应用程序的根目录：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>RedirectResponse</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 将用户从应用程序中登出。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">logout</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">RedirectResponse</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">logout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">invalidate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">regenerateToken</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="使其他设备上的-session-失效" tabindex="-1"><a class="header-anchor" href="#使其他设备上的-session-失效"><span>使其他设备上的 session 失效</span></a></h3>
<p>Laravel 还提供了这样一种机制，可以使在其他设备上处于活动状态的用户 session 无效和「登出」，而不会使其当前设备上的 session 失效。当用户正在更改或更新其密码，并且你希望在保持当前设备身份验证的同时使其他设备上的 session 无效时，通常会使用此功能。</p>
<p>在开始之前，你应该确保 <code v-pre>Illuminate\Session\Middleware\AuthenticateSession</code> 中间件包含在应该接收会话认证的路由上。通常，你应该将这个中间件放到路由组定义中，这样它就可以应用于应用程序的大多数路由。默认情况下，<code v-pre>AuthenticateSession</code> 中间件可以使用 <code v-pre>auth.session</code> <a href="https://learnku.com/docs/laravel/11.x/middlewaremd#middleware-alias" target="_blank" rel="noopener noreferrer">中间件别名</a>附加到路由：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'auth'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'auth.session'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">group</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后，你可以使用 <code v-pre>Auth</code> facade 提供的 <code v-pre>logoutOtherDevices</code> 方法。这个方法要求用户确认他们当前的密码，你的应用程序应该通过输入表单接受这个密码：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">logoutOtherDevices</span><span class="token punctuation">(</span><span class="token variable">$currentPassword</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当调用 <code v-pre>logoutOtherDevices</code> 方法时，用户的其他会话将完全失效，这意味着他们将从之前认证的所有守卫中「登出」。</p>
<h2 id="密码确认" tabindex="-1"><a class="header-anchor" href="#密码确认"><span>密码确认</span></a></h2>
<p>在构建应用程序时，你可能偶尔会要求用户在执行操作之前或在将用户重定向到应用程序的敏感区域之前确认其密码。Laravel 包含内置的中间件，使这个过程变得轻而易举。实现此功能你需要定义两个路由：一个路由显示请求用户确认其密码的视图，另一个路由确认密码有效并将用户重定向到其预期目的地。</p>
<blockquote>
<p><strong>注意</strong><br>
以下文档讨论了如何直接与 Laravel 的密码确认功能集成。然而，如果你想更快地开始使用， <a href="https://learnku.com/docs/laravel/11.x/starter-kitsmd" target="_blank" rel="noopener noreferrer">Laravel 应用入门套件</a> 包括对此功能的支持！</p>
</blockquote>
<h3 id="配置" tabindex="-1"><a class="header-anchor" href="#配置"><span>配置</span></a></h3>
<p>确认密码后，用户在三个小时内不会被要求再次确认密码。但是，你可以通过更改应用程序的 <code v-pre>config/auth.php</code> 配置文件中的 <code v-pre>password_timeout</code> 配置值来配置重新提示用户输入密码之前的时长。</p>
<h3 id="路由" tabindex="-1"><a class="header-anchor" href="#路由"><span>路由</span></a></h3>
<h4 id="密码确认表单" tabindex="-1"><a class="header-anchor" href="#密码确认表单"><span>密码确认表单</span></a></h4>
<p>首先，我们将定义一个路由以显示请求用户确认其密码的视图：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/confirm-password'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">view</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'auth.confirm-password'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'auth'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">name</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'password.confirm'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如你所料，此路由返回的视图应该有一个包含 <code v-pre>password</code> 字段的表单。此外，可以随意在视图中包含说明用户正在进入应用程序的受保护区域并且必须确认其密码的文本。</p>
<h4 id="确认密码" tabindex="-1"><a class="header-anchor" href="#确认密码"><span>确认密码</span></a></h4>
<p>接下来，我们将定义一个路由来处理来自「确认密码」视图的表单请求。此路由将负责验证密码并将用户重定向到其预期目的地：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Hash</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Redirect</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/confirm-password'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span> <span class="token class-name static-context">Hash</span><span class="token operator">::</span><span class="token function">check</span><span class="token punctuation">(</span><span class="token variable">$request</span><span class="token operator">-></span><span class="token property">password</span><span class="token punctuation">,</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">user</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">password</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">back</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">withErrors</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'password'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'The provided password does not match our records.'</span><span class="token punctuation">]</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">passwordConfirmed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">intended</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'auth'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'throttle:6,1'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在继续之前，让我们更详细地检查一下这条路由。首先，请求的 <code v-pre>password</code> 字段被确定为实际匹配经过身份验证的用户的密码。如果密码有效，我们需要通知 Laravel 的 session 用户已经确认了他们的密码。<code v-pre>passwordConfirmed</code> 方法将在用户的 session 中设置一个时间戳，Laravel 可以使用它来确定用户上次确认密码的时间。最后，我们可以将用户重定向到他们想要的目的地。</p>
<h3 id="保护路由-1" tabindex="-1"><a class="header-anchor" href="#保护路由-1"><span>保护路由</span></a></h3>
<p>你应该确保为执行需要最近确认密码的操作的路由被分配到 <code v-pre>password.confirm</code> 中间件。此中间件包含在 Laravel 的默认安装中，并且会自动将用户的预期目的地存储在 session 中，以便用户在确认密码后可以重定向到该位置。在 session 中存储用户的预期目的地之后，中间件将用户重定向到 <code v-pre>password.confirm</code> 的 <a href="https://learnku.com/docs/laravel/11.x/routingmd#named-routes" target="_blank" rel="noopener noreferrer">命名路由</a>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/settings'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'password.confirm'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/settings'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'password.confirm'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="添加自定义守卫" tabindex="-1"><a class="header-anchor" href="#添加自定义守卫"><span>添加自定义守卫</span></a></h2>
<p>你可以使用 <code v-pre>Auth</code> facade 上的 <code v-pre>extend</code> 方法定义你自己的身份验证守卫。你应该在 <a href="https://learnku.com/docs/laravel/11.x/providersmd" target="_blank" rel="noopener noreferrer">服务提供者</a>中调用 <code v-pre>extend</code> 方法。 由于 Laravel 已经附带了 <code v-pre>AuthServiceProvider</code>，因此我们可以将代码放置在该提供者中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Providers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Services<span class="token punctuation">\</span>Auth<span class="token punctuation">\</span>JwtGuard</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Application</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>ServiceProvider</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">AppServiceProvider</span> <span class="token keyword">extends</span> <span class="token class-name">ServiceProvider</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 启动任何应用服务</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">extend</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'jwt'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Application</span> <span class="token variable">$app</span><span class="token punctuation">,</span> <span class="token keyword type-hint">string</span> <span class="token variable">$name</span><span class="token punctuation">,</span> <span class="token keyword type-hint">array</span> <span class="token variable">$config</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// 返回 Illuminate\Contracts\Auth\Guard 的实例...</span></span>
<span class="line"></span>
<span class="line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">JwtGuard</span><span class="token punctuation">(</span><span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">createUserProvider</span><span class="token punctuation">(</span><span class="token variable">$config</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'provider'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>正如上面的示例所示，传递给 <code v-pre>extend</code> 方法的回调函数应该返回 <code v-pre>Illuminate\Contracts\Auth\Guard</code> 的实现。这个接口包含了你需要实现的一些方法来定义一个自定义守卫。一旦你的自定义守卫定义完毕，你可以在 <code v-pre>auth.php</code> 配置文件的 <code v-pre>guards</code> 配置中引用守卫：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'guards'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'api'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'jwt'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'provider'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'users'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="闭包请求守卫" tabindex="-1"><a class="header-anchor" href="#闭包请求守卫"><span>闭包请求守卫</span></a></h3>
<p>实现基于 HTTP 请求的自定义身份验证系统的最简单方法是使用 <code v-pre>Auth::viaRequest</code> 方法。此方法允许你使用单个闭包快速定义身份验证过程。</p>
<p>首先，请在 <code v-pre>AuthServiceProvider</code> 的 <code v-pre>boot</code> 方法中调用 <code v-pre>Auth::viaRequest</code> 方法。<code v-pre>viaRequest</code> 方法接受身份验证驱动程序名称作为其第一个参数。此名称可以是描述你的自定义守卫的任何字符串。传递给方法的第二个参数应该是一个闭包，该闭包接收传入的 HTTP 请求并返回用户实例，或者，如果身份验证失败返回 <code v-pre>null</code>:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 启动任何应用服务。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">viaRequest</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'custom-token'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'token'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword type-casting">string</span><span class="token punctuation">)</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token property">token</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>定义完自定义的身份验证驱动后，你可以在 <code v-pre>auth.php</code> 配置文件的 <code v-pre>guards</code> 配置中将其配置为驱动：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'guards'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'api'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'custom-token'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后，分配认证中间件到路由时，可以引用这个守卫：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'auth:api'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">group</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="添加自定义用户提供者" tabindex="-1"><a class="header-anchor" href="#添加自定义用户提供者"><span>添加自定义用户提供者</span></a></h2>
<p>如果你不是使用传统的关系型数据库来存储用户的，那么你将需要使用你自己的用户认证提供者来扩展 Laravel。我们将使用 <code v-pre>Auth</code> facade 的 <code v-pre>provider</code> 方法来定义自定义的用户提供者。用户提供者解析器应该返回 <code v-pre>Illuminate\Contracts\Auth\UserProvider</code> 的实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Providers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Extensions<span class="token punctuation">\</span>MongoUserProvider</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Application</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>ServiceProvider</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">AppServiceProvider</span> <span class="token keyword">extends</span> <span class="token class-name">ServiceProvider</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 启动任何应用服务。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token class-name static-context">Auth</span><span class="token operator">::</span><span class="token function">provider</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'mongo'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Application</span> <span class="token variable">$app</span><span class="token punctuation">,</span> <span class="token keyword type-hint">array</span> <span class="token variable">$config</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// 返回 Illuminate\Contracts\Auth\UserProvider 的实例...</span></span>
<span class="line"></span>
<span class="line">            <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">MongoUserProvider</span><span class="token punctuation">(</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token function">make</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'mongo.connection'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>使用 <code v-pre>provider</code> 方法注册提供者后，你可以在 <code v-pre>auth.php</code> 配置文件中切换到新的用户提供者。首先，定义一个使用新驱动的 <code v-pre>provider</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'providers'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'users'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'mongo'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后，你可以在 <code v-pre>guards</code> 配置中引用此提供者：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'guards'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'web'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'session'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'provider'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'users'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="用户提供者契约" tabindex="-1"><a class="header-anchor" href="#用户提供者契约"><span>用户提供者契约</span></a></h3>
<p><code v-pre>Illuminate\Contracts\Auth\UserProvider</code> 实现负责从持久存储系统（例如 MySQL、MongoDB 等）中获取 <code v-pre>Illuminate\Contracts\Auth\Authenticatable</code> 的实现。这两个接口允许 Laravel 的身份验证机制继续工作，无论用户数据如何存储或使用什么类型的类来表示认证用户：</p>
<p>我们来看一下 <code v-pre>Illuminate\Contracts\Auth\UserProvider</code> 契约：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">interface</span> <span class="token class-name-definition class-name">UserProvider</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">retrieveById</span><span class="token punctuation">(</span><span class="token variable">$identifier</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">retrieveByToken</span><span class="token punctuation">(</span><span class="token variable">$identifier</span><span class="token punctuation">,</span> <span class="token variable">$token</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">updateRememberToken</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Authenticatable</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token variable">$token</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">retrieveByCredentials</span><span class="token punctuation">(</span><span class="token keyword type-hint">array</span> <span class="token variable">$credentials</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">validateCredentials</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Authenticatable</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token keyword type-hint">array</span> <span class="token variable">$credentials</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">rehashPasswordIfRequired</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Authenticatable</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token keyword type-hint">array</span> <span class="token variable">$credentials</span><span class="token punctuation">,</span> <span class="token keyword type-hint">bool</span> <span class="token variable">$force</span> <span class="token operator">=</span> <span class="token constant boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>retrieveById</code> 函数通常接收代表用户的键，例如 MySQL 数据库中的自增 ID。方法应检索并返回匹配 ID 的 <code v-pre>Authenticatable</code> 实现。</p>
<p><code v-pre>retrieveByToken</code> 函数通过他们独特的 <code v-pre>$identifier</code> 和「记住我」<code v-pre>$token</code>（通常存储在如 <code v-pre>remember_token</code> 的数据库字段中）来检索用户。与前面的方法一样，这个方法应该返回一个拥有匹配 token 值的 <code v-pre>Authenticatable</code> 实现。</p>
<p><code v-pre>updateRememberToken</code> 方法使用新的 <code v-pre>$token</code> 更新 <code v-pre>$user</code> 实例的 <code v-pre>remember_token</code>。成功的「记住我」认证尝试或用户注销时会分配一个新令牌给用户。</p>
<p>尝试使用应用进行认证时，<code v-pre>retrieveByCredentials</code> 方法接收传递给 <code v-pre>Auth::attempt</code> 方法的凭证数组。然后，该方法应该 「查询」底层持久存储中匹配这些凭证的用户。通常，这个方法会执行带有「where」条件的查询，搜索一个「username」 匹配 <code v-pre>$credentials['username']</code> 值的用户记录。该方法应返回一个 <code v-pre>Authenticatable</code> 的实现。<strong>这个方法不应该尝试做任何密码验证或身份认证。</strong></p>
<p><code v-pre>validateCredentials</code> 方法应比较给定的 <code v-pre>$user</code> 与 <code v-pre>$credentials</code> 以认证用户。例如，通常这个方法会使用 <code v-pre>Hash::check</code> 方法比较 <code v-pre>$user-&gt;getAuthPassword()</code> 的值与 <code v-pre>$credentials['password']</code> 的值。这个方法应返回 <code v-pre>true</code> 或 <code v-pre>false</code> 表明密码是否有效。</p>
<p><code v-pre>rehashPasswordIfRequired</code> 方法应该在需要时重新 hash 给定的 <code v-pre>$user</code> 的密码（如果支持）。例如，通常这个方法会使用 <code v-pre>Hash::needsRehash</code> 方法确定 <code v-pre>$credentials['password']</code> 的值是否需要重新 hash 。如果密码需要重新 hash ，方法应使用 <code v-pre>Hash::make</code> 方法重新 hash 密码，并更新底层持久存储中的用户记录。</p>
<h3 id="用户认证契约" tabindex="-1"><a class="header-anchor" href="#用户认证契约"><span>用户认证契约</span></a></h3>
<p>现在我们已经探讨了 <code v-pre>UserProvider</code> 上的每个方法，让我们看一下 <code v-pre>Authenticatable</code> 契约。请记住，用户提供者应从 <code v-pre>retrieveById</code>, <code v-pre>retrieveByToken</code>, 和 <code v-pre>retrieveByCredentials</code> 方法中返回这个接口的实现：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Auth</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">interface</span> <span class="token class-name-definition class-name">Authenticatable</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getAuthIdentifierName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getAuthIdentifier</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getAuthPasswordName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getAuthPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getRememberToken</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">setRememberToken</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getRememberTokenName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这个接口很简单。<code v-pre>getAuthIdentifierName</code> 方法应返回用户的 「主键」列的名称，而 <code v-pre>getAuthIdentifier</code> 方法应返回用户的 「主键」。使用 MySQL 后端时，这通常是分配给用户记录的自增主键。<code v-pre>getAuthPasswordName</code> 方法应返回用户密码列的名称。<code v-pre>getAuthPassword</code> 方法应返回用户的哈希密码。</p>
<p>这个接口可以让身份验证系统与任何「用户」类一起工作，无论你使用什么 ORM 或存储抽象层。默认情况下，Laravel 在 <code v-pre>app/Models</code> 目录中包含一个实现了这个接口的 <code v-pre>App\Models\User</code> 类。</p>
<h2 id="自动密码重组" tabindex="-1"><a class="header-anchor" href="#自动密码重组"><span>自动密码重组</span></a></h2>
<p>Laravel 的默认密码散列算法是 bcrypt。可以通过应用程序的 <code v-pre>config/hashing.php</code> 配置文件或 <code v-pre>BCRYPT_ROUNDS</code> 环境变量来调整 bcrypt 哈希的「工作因子」。</p>
<p>通常，随着 CPU / GPU 处理能力的增加，bcrypt 的工作因子应该随时间增加。如果你提高了应用程序的 bcrypt 工作因子，Laravel 将优雅地并自动地重新 hash 用户密码，因为用户通过 Laravel 的启动工具包或在你通过 <code v-pre>attempt</code> 方法<a href="#authenticating-users">手动认证用户</a>时进行认证。</p>
<p>通常，自动密码重组不应干扰你的应用程序；然而，你可以通过发布 <code v-pre>hashing</code> 配置文件来禁用此行为：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan config:publish hashing</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>在配置文件发布后，你可以将 <code v-pre>rehash_on_login</code> 配置值设置为 <code v-pre>false</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'rehash_on_login'</span> <span class="token operator">=></span> <span class="token constant boolean">false</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="事件" tabindex="-1"><a class="header-anchor" href="#事件"><span>事件</span></a></h2>
<p>在认证过程中，Laravel 会调度各种 <a href="https://learnku.com/docs/laravel/11.x/eventsmd" target="_blank" rel="noopener noreferrer">事件</a>。你可以为以下任何事件<a href="https://learnku.com/docs/laravel/11.x/eventsmd" target="_blank" rel="noopener noreferrer">定义侦听器</a>：</p>
<table>
<thead>
<tr>
<th>事件名称</th>
</tr>
</thead>
<tbody>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Registered</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Attempting</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Authenticated</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Login</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Failed</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Validated</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Verified</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Logout</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\CurrentDeviceLogout</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\OtherDeviceLogout</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\Lockout</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Auth\Events\PasswordReset</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/11.x/authenticationmd/16690" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/au...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/11.x/authenticationmd/16690" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/au...</a></p>
</blockquote>
</div></template>


